package com.eascs.app.context;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import com.eascs.app.exception.InitException;
import com.eascs.common.crypto.RSAUtils;
import com.eascs.common.exception.RuntimeIOException;
import com.eascs.common.util.IoUtil;
import com.eascs.common.util.StringUtil;

public class RSABindConfig {

	private static final String DATA_CONFIG_PUBLIC_KEY_TXT = "/data/config/rsa_public_key.pem";
	private static final String DATA_CONFIG_SECRET_KEY_TXT = "/data/config/pkcs8_rsa_private_key.pem";
	private Map<String, String> privateKeyMap = new HashMap<String, String>();
	private Map<String, String> publicKeyMap = new HashMap<String, String>();

	/**
	 * 获取密钥
	 * 
	 * @param decoder
	 * @return
	 */
	public String getPrivateKey(String privateKeyConfigName) {
		if (!privateKeyMap.containsKey(privateKeyConfigName)) {
			String result = null;
			String privateKeyFile = ConfigContext.getStringValue(privateKeyConfigName, DATA_CONFIG_SECRET_KEY_TXT);
			InputStream inputStream = null;
			try {
				if (privateKeyFile.startsWith("classpath:")) {
					Resource resource = new PathMatchingResourcePatternResolver().getResource(privateKeyFile);
					inputStream = resource.getInputStream();
				} else if (new File(privateKeyFile).exists()) {
					inputStream = new FileInputStream(new File(privateKeyFile));
				}

				if (null != inputStream) {
					result = inputStream2String(inputStream);
				}
			} catch (Exception e) {
				throw new InitException("init secret key err", e);
			} finally {
				IoUtil.close(inputStream);
			}

			privateKeyMap.put(privateKeyConfigName, result);
		}
		return privateKeyMap.get(privateKeyConfigName);
	}

	/**
	 * 获取公钥
	 * 
	 * @param encoder
	 * @return
	 */
	public String getPublicKey(String publicKeyConfigName) {
		String result = publicKeyMap.get(publicKeyConfigName);
		if (result == null) {
			String publicKeyFile = ConfigContext.getStringValue(publicKeyConfigName, DATA_CONFIG_PUBLIC_KEY_TXT);
			File file = new File(publicKeyFile);
			// 如果文件存在则读取密钥
			if (file.exists()) {
				InputStream in = null;
				try {
					in = new FileInputStream(file);
					result = inputStream2String(in);
				} catch (Exception e) {
					throw new InitException("init secret key err", e);
				} finally {
					if (in != null) {
						try {
							in.close();
						} catch (IOException e) {
							throw new RuntimeIOException(e);
						}
					}
				}
				publicKeyMap.put(publicKeyConfigName, result);
			}
		}
		return result;
	}

	public String inputStream2String(InputStream is) throws Exception {
		return RSAUtils.buildKeyFromPemContext(IoUtil.text(is));
	}

	/**
	 * 获取解密后的值
	 * 
	 * @param decoder
	 * @param value
	 * @return
	 */
	public String decode(RSADecoder decoder, String value) {
		if (StringUtil.isEmpty(value)) {
			return value;
		}
		String privateKey = this.getPrivateKey(decoder.privateKey());

		if (StringUtil.isEmpty(privateKey)) {
			// return value when can't load privateKey
			return value;
		}
		return RSAUtils.decryptByPrivateKey(value, privateKey);
	}

	/**
	 * 获取加密后的值
	 * 
	 * @param encoder
	 * @param value
	 * @return
	 */
	public String encode(RSAEncoder encoder, String value) {
		if (StringUtil.isEmpty(value)) {
			return value;
		}
		String publicKey = this.getPublicKey(encoder.publicKey());
		if (StringUtil.isEmpty(publicKey)) {
			// return value when can't load publicKey
			return value;
		}
		return RSAUtils.encryptByPublicKey(value, publicKey);
	}

}
